﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;

public class LangString
{
    int key;
    string text;
    object[] _params;
    uint color;
    bool underline;

    public LangString(int key, params object[] paramList)
    {
        this.key = key;
        _params = paramList;
    }

    public LangString(string text, params object[] paramList)
    {
        this.text = text;
        _params = paramList;
    }

    public object[] GetParams()
    {
        return this._params;
    }

    public void SetParam(int i, object obj)
    {
        if(_params != null && i >= 0 && i < _params.Length)
        {
            this._params[i] = obj;
        }
    }

    public LangString Color(uint c)
    {
        color = c;
        return this;
    }

    public LangString Underline(bool enable)
    {
        underline = enable;
        return this;
    }

    public override string ToString()
    {
        string str = null;
        if (key != 0)
        {
            str = LangManager.Get(key);
        }
        else
        {
            str = text;
        }

        if (str != null)
        {
            if (_params != null)
            {
                if (str != null)
                {
                    str = string.Format(str, _params);
                }
            }

            if (str != null && color != 0)
            {
                str = string.Format("[{1:X8}]{0}[-]", str, color);
            }

            if (str != null && underline)
            {
                str = string.Format("[u]{0}[/u]", str);
            }
        }

        return str;
    }
}

public class LangConfig
{
    public Dictionary<string, int> stringKeyToIntKeyMap;
    public Dictionary<int, string> intKeyToLangMap;

    public override string ToString()
    {
        string str = "";
        str += "stringKeyToIntKeyMap: " + stringKeyToIntKeyMap + "  " + (stringKeyToIntKeyMap == null? 0: stringKeyToIntKeyMap.Count) + "\n";
        str += "intKeyToLangMap: " + intKeyToLangMap + "  " + (intKeyToLangMap == null? 0: intKeyToLangMap.Count) + "\n";
        return str;
    }
}

public class LangAllString
{
    static bool test = false;

    LangConfig langConfig;

    public LangAllString(string str)
    {
        if (str == null)
        {
            return;
        }

        langConfig = JsonConvert.DeserializeObject<LangConfig>(str);
    }

    public string Get(int key)
    {
        string ret = null;
        if (langConfig != null)
        {
            if (langConfig.intKeyToLangMap.TryGetValue(key, out ret))
            {
                if (test)
                {
                    return "test";
                }

                return ret;
            }
        }
        return null;
    }

    public string Get(string key)
    {
        string ret = null;
        int intKey = GetIntKey(key);
        if(intKey != 0)
        {
            if (langConfig.intKeyToLangMap.TryGetValue(intKey, out ret))
            {
                if (test)
                {
                    return "test";
                }

                return ret;
            }
        }
        return null;
    }

    public int GetIntKey(string key)
    {
        if (langConfig != null)
        {
            int intKey = 0;
            if (langConfig.stringKeyToIntKeyMap.TryGetValue(key, out intKey))
            {
                return intKey;
            }
        }
        return 0;
    }

    public Dictionary<string, int> GetReverseMap()
    {
        Dictionary<string, int> reverseMap = new Dictionary<string, int>();
        foreach (var entry in langConfig.intKeyToLangMap)
        {
            if (reverseMap.ContainsKey(entry.Value))
            {
                Debug.LogError("repeat key: " + entry.Value);
                continue;
            }
            reverseMap.Add(entry.Value, entry.Key);
        }
        return reverseMap;
    }

    public override string ToString()
    {
        string str = "";
        str += "test: " + test + "\n";
        str += "langConfig: " + langConfig + "\n";
        return str;
    }
}

public static class LangManager
{
    private const string resDir = "lang_res/";
    public const string dir = "lang";
//    static UnityEngine.SystemLanguage _lang = SystemLanguage.Korean;
    static UnityEngine.SystemLanguage _lang;
    static LangAllString langStrings;
    static UnityEngine.SystemLanguage _defaultLang = UnityEngine.SystemLanguage.ChineseSimplified;
    static LangAllString defaultLangStrings;
    private static char DirSymbol = '~';
    public static System.Func<string, string> externalLoader;

    public static void Reset()
    {
        langStrings = null;
        defaultLangStrings = null;
    }

    static string LoadLangStr(string path)
    {
        TextAsset content = ResourceManager.LoadAsset<TextAsset>(path);
        if (content == null)
        {
            return null;
        }
        string str = content.text;
        Resources.UnloadAsset(content);
        return str;
    }

    public static LangAllString LoadLang(UnityEngine.SystemLanguage lang)
    {
        if (lang == SystemLanguage.Unknown)
        {
            return null;
        }

        string str = null;
        if (externalLoader != null)
        {
            str = externalLoader(dir + "/" + lang);
        }

        if (str == null)
        {
            str = LoadLangStr(dir + "/" + lang);
        }
        if (string.IsNullOrEmpty(str))
        {
            return null;
        }


        LangAllString strings = new LangAllString(str);

        return strings;
    }

    public static void Init()
    {
        if (defaultLangStrings != null)
        {
            return;
        }
        
        defaultLangStrings = LoadLang(_defaultLang);
        ReloadLang();
    }

    public static void ReloadLang()
    {
		if (_lang != _defaultLang)
		{
			langStrings = LoadLang(_lang);
		}
		else
		{
			_lang = UnityEngine.SystemLanguage.Unknown;
			langStrings = null;
		}
    }

    public static void SetLang(UnityEngine.SystemLanguage lang)
    {
        if (_lang == lang)
        {
            return;
        }

        _lang = lang;

        ReloadLang();
    }

    public static UnityEngine.SystemLanguage GetLang()
    {
		if(_lang != SystemLanguage.Unknown)
		{
			return _lang;
		}

		return _defaultLang;
    }

    public static string Get(int key)
    {            
        Init();

        string ret = null;
        if (langStrings != null)
        {
            ret = langStrings.Get(key);
        }

        if (ret == null && defaultLangStrings != null)
        {
            ret = defaultLangStrings.Get(key);
        }

        return ret;
    }

    public static string Get(string key)
    {
        Init();

        string ret = null;
        if (langStrings != null)
        {
            ret = langStrings.Get(key);
        }

        if (ret == null && defaultLangStrings != null)
        {
            ret = defaultLangStrings.Get(key);
        }

        return ret;
    }

    public static int GetIntKey(string key)
    {
        Init();

        int intKey = 0;
        if (langStrings != null)
        {
            intKey = langStrings.GetIntKey(key);
        }

        if (intKey == 0 && defaultLangStrings != null)
        {
            intKey = defaultLangStrings.GetIntKey(key);
        }

        return intKey;
    }
        
	public static string GetResourcePath(string path)
	{
		SystemLanguage curLang = GetLang();
		if (curLang == _defaultLang)
		{
			return path;
		}

		return GetResourcePath(path, curLang);
	}
        
	public static string GetResourcePath(string path, UnityEngine.SystemLanguage language)
	{
		return resDir + language + "/" + path.Replace('/', DirSymbol);
	}
		
	public static string GetNoLangPath(string path)
	{
		int index = path.LastIndexOf('/');
		path = path.Substring(index + 1);
		return path.Replace(DirSymbol, '/');
	}

	public static string GetResDir()
	{
		return resDir;
	}

    public static string GetInfo()
    {
        string info = "";
        info += "_lang: " + _lang + "\n";
        info += "_defaultLang: " + _defaultLang + "\n";
        info += "langStrings: " + langStrings + "\n";
        info += "defaultLangStrings: " + defaultLangStrings + "\n";
        return info;
    }
}
